package com.qinggeng.project.system.service.impl;

import cn.hutool.core.util.IdUtil;
import com.qinggeng.common.constant.Constants;
import com.qinggeng.common.enums.ShowTypeEnum;
import com.qinggeng.common.exception.CustomException;
import com.qinggeng.common.redenvelop.BigDecimalUtil;
import com.qinggeng.common.redenvelop.RedEnvelop;
import com.qinggeng.common.utils.CalendarAdjustUtils;
import com.qinggeng.common.utils.StringUtils;
import com.qinggeng.framework.config.mq.MQSendUtils;
import com.qinggeng.framework.config.mq.dto.MessageMonthLotteryDTO;
import com.qinggeng.framework.config.mq.dto.MessageRedEnvelopesDTO;
import com.qinggeng.framework.config.mq.enums.MQTypeEnum;
import com.qinggeng.framework.redis.RedisCache;
import com.qinggeng.framework.security.LoginUser;
import com.qinggeng.project.api.dto.UserAccountConsumptionDTO;
import com.qinggeng.project.system.domain.*;
import com.qinggeng.project.system.domain.vo.RedEnvelopesActivityVO;
import com.qinggeng.project.system.domain.vo.RedEnvelopesSumMoneyVO;
import com.qinggeng.project.system.domain.vo.RedEnvelopesVO;
import com.qinggeng.project.system.domain.vo.UserActivityInvitVO;
import com.qinggeng.project.system.mapper.UserAccountMapper;
import com.qinggeng.project.system.mapper.UserActivityMapper;
import com.qinggeng.project.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import tk.mybatis.mapper.entity.Example;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class UserActivityServiceImpl implements IUserActivityService {


    @Resource
    private UserActivityMapper userActivityMapper;
    @Resource
    private UserActivityRadEnvelopesService userActivityRadEnvelopesService;

    @Resource
    private UserAccountMapper userAccountMapper;

    @Resource
    private   IUserAccountService userAccountService;

    @Resource
    private DataSourceTransactionManager dataSourceTransactionManager;

    @Resource
    private TransactionDefinition transactionDefinition;
    //拉新
    public  static  final  String INVIT_KEY="10001";



    //默认金额
    public  static  final  String  REDE_NVELOPES_MONEY="2.00";

    //数量
    public   static  final  Integer  REDE_NVELOPES_COUNT=10;


    //默认红包分组
    public  static  final  String  REDE_NVELOPES_ACTIVITY_GROUP_KEY="666666";

    //默认月返现
    public  static  final  String  LOTTERY_PROPORTION_ACTIVITY_GROUP_KEY="777777";


    //是否开启月中奖
    public  static  final  String  LOTTERY_MONTH_PROPORTION_IS_ACTIVITY="10006";

    //年提现比例
    public  static  final  String  YEAR_WITHDRAWAL_PROPORTION="10004";



    @Resource
    private UserAccountConsumptionMonthService userAccountConsumptionMonthService;


    @Resource
    private UserAccountRecordLotteryMonthService userAccountRecordLotteryMonthService;



    @Resource
    private MQSendUtils mqSendUtils;

    @Resource
    private RedisCache redisCache;

    @Resource
    private RedissonClient redissonClient;
    @Override
    public UserActivity getUserActivity(String key) {
        Example example =new Example(UserActivity.class);
        example.setOrderByClause("id desc limit 1");
        example.createCriteria()
                .andEqualTo("activityKey",key)
                .andEqualTo("status",0);
        UserActivity userActivity= userActivityMapper.selectOneByExample(example);
        return userActivity;
    }

    @Override
    public String getYearWithdrawalProportion() {
        UserActivity userActivity=getUserActivity(YEAR_WITHDRAWAL_PROPORTION);
        if (userActivity == null) {
            return BigDecimal.ZERO.toString();
        }
        return userActivity.getActivityValue();
    }


    @Override
    public UserActivityInvitVO getUserActivityInvitVO() {
        UserActivity userActivity=getUserActivity(INVIT_KEY);
        if (null==userActivity){
            throw new CustomException("当前活动不存在");
        }
        Integer status=userActivity.getStatus();
        if (status == 1){
            throw new CustomException("当前活动還沒開始或者已经停止");
        }
        UserActivityInvitVO userActivityInvitVO =new UserActivityInvitVO();
        userActivityInvitVO.setArg(userActivity.getActivityParam());
        userActivityInvitVO.setCode(userActivity.getActivityCode().toString());
        userActivityInvitVO.setIsReturn(userActivity.getActivityValue());
        userActivityInvitVO.setUrl(userActivity.getActivityImage());
        return userActivityInvitVO;
    }


    @Override
    public RedEnvelopesActivityVO checkRedEnvelopes(Long userId) {
        RedEnvelopesActivityVO vo=new RedEnvelopesActivityVO();

        UserActivity userActivity=getUserActivity();
        if (userActivity == null){
            vo.setHaveActivity(false);
            return vo;
        }
        vo.setHaveActivity(true);
        vo.setCount(userActivity.getActivityCount());
        vo.setImgUrl(userActivity.getActivityImage());
        vo.setUrl(userActivity.getActivityParam());
        vo.setActivityKey(userActivity.getActivityKey());
        //活动 进行中
        vo.setStatus(1);
        LocalDateTime localDateTime=LocalDateTime.now();
        int nowHour=localDateTime.getHour();
        Integer begin=Integer.valueOf(userActivity.getBeginTime());
        if (nowHour>(begin+1)){
            vo.setStatus(3);
            return vo;
        }
        if (null != userId){
            UserActivityReaEnvelopes reaEnvelopes=userActivityRadEnvelopesService.getUserActivityRedEnvelopes(userId,userActivity.getActivityKey(),new Date());
            if (reaEnvelopes!=null){
                //活动结束
                vo.setStatus(3);
            }
        }
        if (null == userId){
            vo.setStatus(3);
        }
        return vo;
    }

    @Override
    public RedEnvelopesActivityVO checkRedEnvelopes(String token) {
        String key= Constants.API_TOKEN_KEY+token;
        LoginUser loginUser=redisCache.getCacheObject(key);
        Long  userId=null;
        if (loginUser!=null){
            SysUser user=loginUser.getUser();
            userId=user.getUserId();
        }
        return  checkRedEnvelopes(userId);
    }

    private UserActivity getUserActivity() {
        Example example =new Example(UserActivity.class);
        example.setOrderByClause("id desc limit 1");
        example.createCriteria()
                .andEqualTo("status",0)
                .andEqualTo("delFalg",0)
                .andEqualTo("activityGroupKey",REDE_NVELOPES_ACTIVITY_GROUP_KEY);
        UserActivity userActivity=userActivityMapper.selectOneByExample(example);
        return userActivity;
    }


    @Override
    public  List<UserActivity> listOpenRedEnvelopes() {
        List<UserActivity> userActivities=listUserActivity(REDE_NVELOPES_ACTIVITY_GROUP_KEY);
        return userActivities;
    }
    @Override
    public  List<UserActivity> listRedEnvelopes() {
        Example example =new Example(UserActivity.class);
        example.createCriteria()
                .andEqualTo("delFalg",0)
                .andEqualTo("activityGroupKey",REDE_NVELOPES_ACTIVITY_GROUP_KEY);
        List<UserActivity> userActivities=userActivityMapper.selectByExample(example);
        return userActivities;
    }

    private  List<UserActivity> listUserActivity(String groupKey) {
        Example example =new Example(UserActivity.class);
        example.createCriteria()
                .andEqualTo("status",0)
                .andEqualTo("delFalg",0)
                .andEqualTo("activityGroupKey",groupKey);
        List<UserActivity> userActivities=userActivityMapper.selectByExample(example);
        return userActivities;
    }

    @Override
    public List<RedEnvelopesVO> grabredEnvelopes(Long userId) {
        RedEnvelopesSumMoneyVO vo= this.grabredRedEnvelopesSumMoneyVO(userId);
        if (null == vo){
            throw new CustomException("RedEnvelopesSumMoneyVO is null");
        }
        List<RedEnvelopesVO> list=vo.getList();
        if (null == list){
            throw new CustomException("List<RedEnvelopesVO> list is null");
        }
        return list;
    }

    @Override
    public RedEnvelopesSumMoneyVO grabredRedEnvelopesSumMoneyVO(Long userId) {

        RedEnvelopesActivityVO redEnvelopesActivityVO=checkRedEnvelopes(userId);
        //展示给前台状态 等于1 时才开启红包活动
        Integer status=redEnvelopesActivityVO.getStatus();
        if (status !=1){
            throw  new CustomException("不满足参与活动条件", ShowTypeEnum.用户.getValue());
        }
        String key= redEnvelopesActivityVO.getActivityKey();
        //查看今天是不参了活动
        userActivityRadEnvelopesService.checkUserActivityRedEnvelopes(userId,key,new Date());
        UserActivity userActivity=getUserActivity(key);
        BigDecimal  money=new BigDecimal(REDE_NVELOPES_MONEY);
        String value=userActivity.getActivityValue();
        if (StringUtils.isNotEmpty(value)){
            money=new BigDecimal(value);
        }
        Integer count =REDE_NVELOPES_COUNT;
        Integer activityCount=userActivity.getActivityCount();
        if (activityCount !=null ){
            count=activityCount;
        }
        //随机递减金额
        double sub =new Random().nextDouble();
        money= BigDecimalUtil.subtract(money,new BigDecimal(sub));
        RedEnvelop red = new RedEnvelop(count, money.floatValue());
        BigDecimal b = new BigDecimal(0);

        //获取红包
        List<RedEnvelopesVO> list=new ArrayList<>();
        for(int i = 0; i< red.getCount(); i++){
            RedEnvelopesVO vo=new RedEnvelopesVO();
            BigDecimal m = red.nextRed();
            vo.setMoney(m.toString());
            list.add(vo);
            b = b.add(m);
        }
        RedEnvelopesSumMoneyVO redEnvelopesSumMoneyVO=new RedEnvelopesSumMoneyVO();
        redEnvelopesSumMoneyVO.setList(list);
        redEnvelopesSumMoneyVO.setSumMoney(b.toString());

        userAccountService.checkFilterUserAccount(userId);

        String lockKey= UserAccountServiceImpl.USER_ACCOUNT+userId;
        RLock lock=redissonClient.getLock(lockKey);
        if (lock.isLocked()){
            throw  new CustomException("已经提交请稍后");
        }
        lock.lock(5,TimeUnit.SECONDS);

        TransactionStatus transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);
        try {
            UserActivityReaEnvelopes userActivityRadEnvelopes=new UserActivityReaEnvelopes();
            userActivityRadEnvelopes.setUserId(userId);
            userActivityRadEnvelopes.setActivityKey(key);
            userActivityRadEnvelopesService.insertUserActivityRedEnvelopes(userActivityRadEnvelopes);

            UserAccount userAccount=new UserAccount();
            userAccount.setUserId(userId);
            userAccount.setAccount(b);
            userAccountMapper.addUserAccountMoney(userAccount);
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException("红包活动异常", ShowTypeEnum.用户.getValue());
        }
        MessageRedEnvelopesDTO redEnvelopesDTO=new MessageRedEnvelopesDTO();
        redEnvelopesDTO.setUserId(userId);
        redEnvelopesDTO.setType(MQTypeEnum.RED_ENVRLOPES.getType());
        redEnvelopesDTO.setMoney(b.toString());
        mqSendUtils.sendAsynMessage(redEnvelopesDTO);
        return redEnvelopesSumMoneyVO;
    }

    @Override
    public List<String> listLotteryProportionMonth() {

        UserActivity userActivity= getUserActivity(LOTTERY_MONTH_PROPORTION_IS_ACTIVITY);
        if (null == userActivity){
            throw  new CustomException("活动未开启");
        }
        if (userActivity.getDelFalg()!=0){
            throw  new CustomException("活动未开启");
        }
        if (userActivity.getStatus()!=0){
            throw  new CustomException("活动未开启");
        }
        List<UserActivity> userActivities=listUserActivity(LOTTERY_PROPORTION_ACTIVITY_GROUP_KEY);
        if (null == userActivities ||userActivities.isEmpty() ){
            throw  new CustomException("活动未设置中奖比例");
        }
        List<String> list=new ArrayList<>();
        for (int i = 0; i < userActivities.size(); i++) {
            list.add(userActivities.get(i).getActivityValue());
        }
        return list;
    }

    @Override
    public String getLotteryProportionMonth(Long userId) {
        List<String> list=listLotteryProportionMonth();
        boolean month1stTo7th= CalendarAdjustUtils.checkMonth1stTo7th();
        if (month1stTo7th ==false){
            throw  new CustomException("每月1号到7号才可以提现上月返现金额");
        }
        UserAccountRecordLotteryMonth month= userAccountRecordLotteryMonthService.getUserAccountRecordLotteryMonth(userId);
        if (null != month){
            return month.getProportion().toString();
        }
        UserAccountConsumptionMonth userAccountConsumptionMonth=new UserAccountConsumptionMonth();
        userAccountConsumptionMonth.setUserId(userId);
        userAccountConsumptionMonth.setCreateMonth(CalendarAdjustUtils.getLastMonthToStr());
        userAccountConsumptionMonth= userAccountConsumptionMonthService.getUserAccountConsumption(userAccountConsumptionMonth);
        if (userAccountConsumptionMonth == null){
            throw  new CustomException("当月无消费记录");
        }
        BigDecimal thisMonthCanBeWifthdrawn=userAccountConsumptionMonth.getThisMonthCanBeWifthdrawn();
        if (thisMonthCanBeWifthdrawn.compareTo(BigDecimal.ZERO)<=0){
            throw  new CustomException("提现额度不能为0");
        }
        BigDecimal thisMonthConsumption=userAccountConsumptionMonth.getThisMonthConsumption();
        BigDecimal lastMonthConsumption=userAccountConsumptionMonth.getLastMonthConsumption();
        if (thisMonthConsumption.compareTo(lastMonthConsumption)<=0){
            throw  new CustomException("您的本月消费金额未达到上月的消费金额，不能转到零钱！");
        }

        int index=new Random().nextInt(list.size());
        String proporTion=list.get(index);
        BigDecimal bl=new BigDecimal(proporTion);
        BigDecimal money=BigDecimalUtil.multiply(thisMonthConsumption,bl);

        userAccountService.checkFilterUserAccount(userId);
        UserAccountRecordLotteryMonth m=new UserAccountRecordLotteryMonth();
        m.setType(MQTypeEnum.MONTH_LOTTERY_ACCOUNT.getType());
        m.setProportion(bl);
        m.setMoney(money);
        m.setUserId(userId);
        Long messageId= IdUtil.getSnowflake(1L,1L).nextId();
        m.setMessageId(messageId);
        m.setCalculation(1);
        userAccountRecordLotteryMonthService.checkUserAccountRecordLotteryMonth(m);
        return proporTion;
    }

    @Override
    public String getLotteryProportionMonthUpdateAccount(Long userId) {

        UserAccountRecordLotteryMonth month= userAccountRecordLotteryMonthService.getUserAccountRecordLotteryMonth(userId);
        if (null == month){
            throw  new CustomException("先去开启抽奖转盘");
        }
        String lockKey= UserAccountServiceImpl.USER_ACCOUNT+userId;
        RLock lock=redissonClient.getLock(lockKey);
        if (lock.isLocked()){
            throw  new CustomException("已经提交请稍后");
        }
        lock.lock(5,TimeUnit.SECONDS);
        userAccountService.checkFilterUserAccount(userId);
        TransactionStatus transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);
        try {
            Long id=month.getId();
            boolean bl=userAccountRecordLotteryMonthService.updateAccountRecordLotteryMonthCalculation(id);
            if (bl==false){
                throw  new CustomException("已经提交请稍后");
            }
            UserAccount userAccount=new UserAccount();
            userAccount.setUserId(userId);
            userAccount.setAccount(month.getMoney());
            userAccountMapper.addUserAccountMoney(userAccount);

            UserAccountConsumptionDTO dto=new UserAccountConsumptionDTO();
            dto.setUserId(userId);
            dto.setMoney(month.getMoney().toString());
            userAccountConsumptionMonthService.goToSmallChangeClean(dto);
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
        }

        MessageMonthLotteryDTO messageMonthLotteryDTO =new MessageMonthLotteryDTO();
        messageMonthLotteryDTO.setMessageId(month.getMessageId());
        messageMonthLotteryDTO.setUserId(userId);
        messageMonthLotteryDTO.setMoney(month.toString());
        String  proporTion=month.getProportion().toString();
        messageMonthLotteryDTO.setProportion(proporTion);
        messageMonthLotteryDTO.setType(MQTypeEnum.MONTH_TURNTABLE_LOTTERY_ACCOUNT.getType());
        mqSendUtils.sendAsynMessage(messageMonthLotteryDTO);
        return proporTion;
    }

    @Override
    public String notIsItAMonthlyLottery(Long userId) {
        listLotteryProportionMonth();
        boolean month1stTo7th=CalendarAdjustUtils.checkMonth1stTo7th();
        if (month1stTo7th ==false){
            throw  new CustomException("每月1号到7号才可以提现上月返现金额");
        }

        UserAccountRecordLotteryMonth month= userAccountRecordLotteryMonthService.getUserAccountRecordLotteryMonth(userId);
        if (null != month){
            throw  new CustomException("每月只能有一次机会将上月返现金额转入到零钱");
        }
        UserAccountConsumptionMonth userAccountConsumptionMonth=new UserAccountConsumptionMonth();
        userAccountConsumptionMonth.setUserId(userId);
        userAccountConsumptionMonth.setCreateMonth(CalendarAdjustUtils.getLastMonthToStr());
        userAccountConsumptionMonth= userAccountConsumptionMonthService.getUserAccountConsumption(userAccountConsumptionMonth);
        if (userAccountConsumptionMonth == null){
            throw  new CustomException("当月无消费记录");
        }
        BigDecimal thisMonthCanBeWifthdrawn=userAccountConsumptionMonth.getThisMonthCanBeWifthdrawn();
        if (thisMonthCanBeWifthdrawn.compareTo(BigDecimal.ZERO)<=0){
            throw  new CustomException("提现额度不能为0");
        }
        BigDecimal thisMonthConsumption=userAccountConsumptionMonth.getThisMonthConsumption();
        BigDecimal lastMonthConsumption=userAccountConsumptionMonth.getLastMonthConsumption();
        if (thisMonthConsumption.compareTo(lastMonthConsumption)<=0){
            throw  new CustomException("您的本月消费金额未达到上月的消费金额，不能转到零钱！");
        }
        String lockKey= UserAccountServiceImpl.USER_ACCOUNT+userId;
        RLock lock=redissonClient.getLock(lockKey);
        if (lock.isLocked()){
            throw  new CustomException("已经提交请稍后");
        }
        lock.lock(5,TimeUnit.SECONDS);
        userAccountService.checkFilterUserAccount(userId);
        UserAccount userAccount=new UserAccount();
        userAccount.setUserId(userId);
        userAccount.setAccount(thisMonthCanBeWifthdrawn);
        userAccountMapper.addUserAccountMoney(userAccount);

        MessageMonthLotteryDTO dto =new MessageMonthLotteryDTO();
        dto.setUserId(userId);
        dto.setMoney(thisMonthCanBeWifthdrawn.toString());
        String  proporTion=BigDecimal.ONE.toString();
        dto.setProportion(proporTion);
        dto.setType(MQTypeEnum.MONTH_LOTTERY_ACCOUNT.getType());
        mqSendUtils.sendAsynMessage(dto);
        return proporTion;
    }

    private boolean updateStatusOpen(Long id) {
        UserActivity userActivity=new UserActivity();
        userActivity.setId(id);
        userActivity.setStatus(0);
        return userActivityMapper.updateByPrimaryKeySelective(userActivity)>=1;
    }


    @Override
    public boolean openRedEnvelopesAvtivity(Long id) {
        Example example =new Example(UserActivity.class);
        example.createCriteria()
                .andEqualTo("activityGroupKey",REDE_NVELOPES_ACTIVITY_GROUP_KEY);
        UserActivity userActivity=new UserActivity();
        userActivity.setStatus(1);
        userActivityMapper.updateByExampleSelective(userActivity,example);
        return updateStatusOpen(id);
    }

    @Override
    public boolean updateStatusOpen(String key) {
        Example example =new Example(UserActivity.class);
        example.createCriteria()
                .andEqualTo("activityKey",key);
        UserActivity userActivity=new UserActivity();
        userActivity.setStatus(0);
        return userActivityMapper.updateByExampleSelective(userActivity,example)>0;
    }

    @Override
    public boolean updateStatusClose(String key) {
        Example example =new Example(UserActivity.class);
        example.createCriteria()
                .andEqualTo("activityKey",key);
        UserActivity userActivity=new UserActivity();
        userActivity.setStatus(1);
        return userActivityMapper.updateByExampleSelective(userActivity,example)>0;
    }

}
